/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "节点编辑.h"
#include "Context/数据创建销毁.h"



void f_NE_骨骼物体状态颜色设置(const std::vector<S_物体*>& obs) {
	for (auto& e : obs) {
		auto* 骨架 = e->m_子物体[0];
		auto* 骨节 = e->m_子物体[1];

		f_surface_fill颜色(f_ob_fromMesh(骨架, 0), S_节点UI主题::uic_骨骼边物体状态, 0, -1);
		f_surface_fill颜色(f_ob_fromMesh(骨架, 1), S_节点UI主题::uic_骨骼面物体状态, 0, -1);

		f_surface_fill颜色(f_ob_fromMesh(骨节, 0), S_节点UI主题::uic_骨骼边物体状态, 0, -1);
		f_surface_fill颜色(f_ob_fromMesh(骨节, 1), S_节点UI主题::uic_骨骼面物体状态, 0, -1);
	}
}

void f_NE_骨骼编辑状态颜色设置(const std::vector<S_物体*>& obs) {
	for (auto& e : obs) {
		auto* 骨架 = e->m_子物体[0];
		auto* 骨节 = e->m_子物体[1];

		f_surface_fill颜色(f_ob_fromMesh(骨架, 0), S_节点UI主题::uic_骨骼边编辑状态, 0, -1);
		f_surface_fill颜色(f_ob_fromMesh(骨架, 1), S_节点UI主题::uic_骨骼面编辑状态, 0, -1);

		f_surface_fill颜色(f_ob_fromMesh(骨节, 0), S_节点UI主题::uic_骨骼边编辑状态, 0, -1);
		f_surface_fill颜色(f_ob_fromMesh(骨节, 1), S_节点UI主题::uic_骨骼面编辑状态, 0, -1);
	}
}

void f_NE_拷贝物体(const S_OBArray* obs, uint32 拷贝数量, S_OBArray* 新物体组, bool 是否实例, S_设备环境& ctx) {
	uint32 输入组数量 = obs->count;
	uint32 实例总数 = 输入组数量 * 拷贝数量;

	
	for (uint32 j = 0; j < 输入组数量; ++j) {
		auto& 被拷贝的物体 = obs->ptr_userData[j];

		if (是否实例) {
			//新物体组.resize(实例总数);
			f_core_array_resize((S_Array*)新物体组, 实例总数);

			for (uint32 i = 0; i < 拷贝数量; ++i) {
				uint32 offset = 拷贝数量 * j + i;

				//S_物体* 新拷贝物体 = 新物体组[offset];
				S_物体* 新拷贝物体 = 新物体组->ptr_userData[offset];
				if (新拷贝物体 == nullptr) {
					新拷贝物体 = f_NodeCtx_回收物体();
					if (!新拷贝物体) 新拷贝物体 = f_ob_创建物体(ctx, E_物体类型::t_网格);

					新物体组->ptr_userData[offset] = 新拷贝物体;
				}
			
				f_ob_改变物体类型(新拷贝物体, obs->ptr_userData[j]->m_Type, ctx);
				f_ob_link物体数据(新拷贝物体, 被拷贝的物体);
				f_ob_set实例数量(新拷贝物体, 拷贝数量);
			
			
				
				S_物体* ob = f_NodeCtx_回收物体();
				if (ob == nullptr) {
					ob = f_ob_创建物体实例(nullptr, i);
				}
				ob->m_实例ID = i;

				f_ob_add子物体(新拷贝物体, ob, i);
			}

		}
		else {
			//新物体组.resize(实例总数);
			f_core_array_resize((S_Array*)新物体组, 实例总数);

			for (uint32 i = 0; i < 拷贝数量; ++i) {
				auto* 新物体 = f_ob_copy物体数据(ctx, 被拷贝的物体);

				uint32 offset = 拷贝数量 * j + i;
				新物体组->ptr_userData[offset] = 新物体;
				新物体组->ptr_userData[offset]->m_Name = L"深度拷贝物体";

			}
		}
	}

}

void f_NE_拷贝物体(const S_OBArray* obs, uint32 拷贝数量, S_物体* 新物体的父物体, S_OBArray* 新物体组, bool 是否实例, S_设备环境& ctx) {
	//uint32 输入组数量 = obs.size();
	uint32 输入组数量 = obs->count;
	
	uint32 实例总数 = 输入组数量 * 拷贝数量;
	//新物体组.resize(实例总数);
	f_core_array_resize((S_Array*)新物体组, 实例总数);

	f_ob_clear子物体(新物体的父物体);

	for (uint32 j = 0; j < 输入组数量; ++j) {
		auto* 被拷贝的物体 = obs->ptr_userData[j];

		if (是否实例) {
			S_物体* 新拷贝物体 = f_NodeCtx_回收物体();
			if (!新拷贝物体) 新拷贝物体 = f_ob_创建物体(ctx, E_物体类型::t_网格);

			if (被拷贝的物体->m_是否实例) {
				被拷贝的物体 = f_ob_get父变换对象(被拷贝的物体);
			}

			f_ob_改变物体类型(新拷贝物体, 被拷贝的物体->m_Type, ctx);
			f_ob_link物体数据(新拷贝物体, 被拷贝的物体);
			f_ob_set实例数量(新拷贝物体, 拷贝数量);

			f_node_网格绘制属性设置(新拷贝物体);

			switch (被拷贝的物体->m_Type) {
				case E_物体类型::t_包: {
					S_VkDrawIndirectCommand indirect = f_surface_get间接绘制区间(f_ob_fromMesh(被拷贝的物体, 0), 0);
					indirect.firstInstance = 0;
					indirect.instanceCount = 拷贝数量;
					f_surface_add间接绘制(f_ob_fromMesh(新拷贝物体, 0), indirect);
					break;
				}
			}
			 

			//新拷贝物体->f_打开可视通道(0);
			for (uint32 i = 0; i < 拷贝数量; ++i) {
				uint32 offset = 拷贝数量 * j + i;

				S_物体* ob = f_NodeCtx_回收物体();
				if (ob == nullptr) {
					ob = f_ob_创建物体实例(nullptr, i);
				}
				else {
					f_ob_改变物体类型(ob, E_物体类型::t_实例, ctx);
				}
				ob->m_实例ID = i;

				新物体组->ptr_userData[offset] = ob;
				f_ob_set实例物体(新拷贝物体, ob, i);



				f_ob_set颜色2(ob, {}, ob->m_实例ID);
				f_ob_set颜色2(ob, S_节点UI主题::uic_模型面, ob->m_实例ID, 1);
				f_ob_set颜色2(ob, S_节点UI主题::uic_模型线, ob->m_实例ID, 2);
			}

			新拷贝物体->m_实例ID = 0;
			新拷贝物体->m_根实例 = true;
			f_ob_add子物体(新物体的父物体, 新拷贝物体, j);
		}
		else {
			//S_物体* 新拷贝物体 = f_NodeCtx_回收物体();
			//if (新拷贝物体) {
			//	
			//}
			//else {
			//	新拷贝物体 = f_ob_创建物体(ctx, 被拷贝的物体->m_Type);
			//}
			for (uint32 i = 0; i < 拷贝数量; ++i) {
				uint32 offset = 拷贝数量 * j + i;

				S_物体* 新拷贝物体 = 新物体组->ptr_userData[offset];
				//if (新拷贝物体) {
				//	if (新拷贝物体->m_Type != 被拷贝的物体->m_Type) {
				//		f_ob_改变物体类型(新拷贝物体, 被拷贝的物体->m_Type, ctx);
				//		f_node_创建网格物体数据(新拷贝物体, ctx);
				//	}
				//}
				
				switch (被拷贝的物体->m_Type) {
				case E_物体类型::t_网格: {
					新拷贝物体 = f_node_网格节点创建物体数据(ctx);
					f_surface_Copy(f_ob_fromMesh(新拷贝物体, 0), f_ob_fromMesh(被拷贝的物体, 0));
					break;
				}
				case E_物体类型::t_多边形: {
					新拷贝物体 = f_ob_创建物体(E_物体类型::t_多边形, 被拷贝的物体, ctx);
					f_node_构建多边形网格对象(ctx, 新拷贝物体);
					f_surface_Copy(f_ob_fromMesh(新拷贝物体, 0), f_ob_fromMesh(被拷贝的物体, 0));
					f_surface_Copy(f_ob_fromMesh(新拷贝物体, 2), f_ob_fromMesh(被拷贝的物体, 2));
					f_surface_Copy(f_ob_fromMesh(新拷贝物体, 3), f_ob_fromMesh(被拷贝的物体, 3));
					break;
				}
				default:
					新拷贝物体 = f_ob_创建物体(ctx, E_物体类型::t_虚拟体);
					break;
				}

				新拷贝物体->m_isUpdate = true;
				新拷贝物体->m_实例ID = 0;
				新拷贝物体->m_根实例 = true;

				新物体组->ptr_userData[offset] = 新拷贝物体;

				f_ob_add子物体(新物体的父物体, 新拷贝物体);
			}
		}
	}
}

static void f_对称变换坐标(const S_Tranform& t1, S_Tranform& t2, bool 对称轴[3], vec3 中心坐标) {
	if (对称轴[0]) {
		t2.location.x = 中心坐标.x - (t1.location.x - 中心坐标.x);
	}
	if (对称轴[1]) {
		t2.location.y = 中心坐标.y - (t1.location.y - 中心坐标.y);
	}
	if (对称轴[2]) {
		t2.location.z = 中心坐标.z - (t1.location.z - 中心坐标.z);
	}
}
void f_NE_对称物体(const std::vector<S_物体*>& obs, std::vector<S_物体*>& 新物体组, bool 对称轴[3], vec3 中心坐标) {
	uint32 num = obs.size();
	for (uint32 i = 0; i < num; ++i) {
		f_对称变换坐标(obs[i]->m_变换, 新物体组[i]->m_变换, 对称轴, 中心坐标);
		
		if (obs[i]->m_UserData) {
			switch (obs[i]->m_Type)
			{
			case E_物体类型::t_骨骼: {
				S_物体* 骨节物体 = (S_物体*)obs[i]->m_UserData;
				S_物体* 新骨节物体 = (S_物体*)新物体组[i]->m_UserData;
				f_对称变换坐标(骨节物体->m_变换, 新骨节物体->m_变换, 对称轴, 中心坐标);
				break;
			}
			default:
				break;
			}
		}
		
		f_NE_对称物体(obs[i]->m_子物体, 新物体组[i]->m_子物体, 对称轴, 中心坐标);
	}
}





void f_NE_多边形转网格(S_物体* Ob, bool 平滑法线) {
	S_多边形* 多边形 = (S_多边形*)Ob->m_UserData;

#pragma omp parallel sections
	{
	#pragma omp section
		{
			uint32 num = 多边形->m_顶点.size();
			std::vector<S_VNT1> 面顶点(num);
			std::vector<S_VC> 顶点(num);
			auto* vert_ptr = 面顶点.data();
			for (uint32 i = 0; i < num; ++i) {
				顶点[i].vert = vert_ptr[i].vert = 多边形->m_顶点[i];
				顶点[i].color = f_PackData4X8({ 127,127,0,255 });

				vert_ptr[i].normal = {};
				vert_ptr[i].UV = {};
			}
			auto* 点网格 = f_ob_fromMesh(Ob, 2);
			f_surface_fill顶点数据(点网格, 顶点);


			num = 多边形->m_面.size();
			if (num) {
				auto* 面 = f_ob_fromMesh(Ob, 1);
				f_surface_fill顶点数据(面, 面顶点);
				f_surface_多边形三角化(面, 多边形);
				//f_surface_fill层纹理坐标(面, m_多边形[polyID].m_UV);

				auto mat = f_mat44_identity();

				if (平滑法线) {
					std::vector<std::vector<uint32>> 顶点相邻面;
					f_surface_构建顶点相连面索引(面, 顶点相邻面);
					f_surface_计算面平滑法线(面, 顶点相邻面);
				}
			}

			f_surface_计算包围盒(f_ob_fromMesh(Ob, 0));
		}
	#pragma omp section
		{
			uint32 边数量 = 多边形->m_边.size();
			std::vector<S_VC> 顶点边;
			顶点边.reserve(边数量 * 2);
			for (uint32 i = 0; i < 边数量; ++i) {
				uint32 边数量 = 多边形->m_边[i]->edge.size();

				auto edge = 多边形->m_边[i]->edge.data();
				for (uint32 j = 0; j < 边数量; ++j) {
					uint32 id = i * 边数量 + j;
					S_VC v;
					v.vert = 多边形->m_顶点[edge[j].x];
					v.color = f_PackData4X8({ 0,0,0,255 });
					顶点边.push_back(v);

					v.vert = 多边形->m_顶点[edge[j].y];
					v.color = f_PackData4X8({ 0,0,0,255 });
					顶点边.push_back(v);
				}
			}
			auto* 线 = f_ob_fromMesh(Ob, 3);
			f_surface_fill顶点数据(线, 顶点边);
		}
	}

	f_scene_更新物体渲染(f_NodeCtx_get默认场景(), Ob);

}








static std::map<S_物体*, S_可编辑物体*> g可编辑物体容器;

S_可编辑物体* f_OE_创建可编辑物体属性(S_物体* ob) {
	S_可编辑物体* eo;
	if (g可编辑物体容器.find(ob) != g可编辑物体容器.end()) {
		uint32 size = sizeof(S_可编辑物体);
		eo = new S_可编辑物体;
		eo->m_Ob = ob;

		eo->m_当前激活UV层 = f_alloc_UI32FlagBitsProp(nullptr, L"激活UV层");
		eo->m_当前激活UV层.m_私有 = true;
		f_prop_UI32(eo->m_当前激活UV层) = 1;

		g可编辑物体容器[ob] = eo;
	}
	else {
		eo = g可编辑物体容器[ob];
	}

	return eo;
}

S_可编辑物体* f_OE_取可编辑物体属性(S_物体* ob) {
	if (g可编辑物体容器.find(ob) != g可编辑物体容器.end()) {
		return g可编辑物体容器[ob];
	}
	return nullptr;
}

void f_OE_销毁可编辑物体属性(S_物体* ob) {
	if (g可编辑物体容器.find(ob) != g可编辑物体容器.end()) {
		delete (g可编辑物体容器[ob]);

		g可编辑物体容器.erase(ob);
	}
}

void f_OE_销毁所有可编辑物体属性() {
	for (auto& e : g可编辑物体容器) {
		delete (e.second);
	}

	g可编辑物体容器.clear();
}


